package com.vcc.web.core.component;

import com.alibaba.fastjson2.JSONObject;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.vcc.core.exception.ProgramException;
import com.vcc.core.util.JsonUtil;
import com.vcc.core.util.RegexUtil;
import com.vcc.web.core.config.AliConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class AliComponent {

    @Autowired
    private AliConfig aliConfig;
    @Autowired
    private RestTemplate restTemplate;

    //------------------------------------------获取IP地址方法区-----------------------------------------------------

    public JSONObject ipToAddress(String ip) {
        JSONObject resultMap;
        try {
            String url = aliConfig.getIpUrl() + "?ip=" + ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip) ? "localhost" : ip);
            resultMap = getForBaseMap(url);
            if (RegexUtil.checkObjectIsNull(resultMap)) {
                throw new ProgramException("系统异常");
            }
            if ("200".equals(resultMap.getString("ret"))) {
                resultMap = resultMap.getJSONObject("data");
            }
        } catch (Exception e) {
            resultMap = null;
        }
        return resultMap;
    }

    //------------------------------------------获取IP地址方法区-----------------------------------------------------


    //------------------------------------------获取汇率方法区-----------------------------------------------------

    private final LoadingCache<String, BigDecimal> graphs = Caffeine.newBuilder()
            //过期时间
            .expireAfterWrite(2, TimeUnit.MINUTES)
            .build(this::rate);

    private BigDecimal rate(String key) {
        List<String> keys = Arrays.asList(key.split("\\|"));
        String sourceCode = keys.get(0);
        String toCode = keys.get(1);
        try {
            String url = aliConfig.getRateUrl() + "?amount=1&from=" + sourceCode + "&to=" + toCode;
            JSONObject result = getForBaseMap(url);
            if (result.getIntValue("status")==0) {
                JSONObject dataMap = result.getJSONObject("result");
                return dataMap.getBigDecimal("rate");
            }else {
                return BigDecimal.valueOf(-1);
            }
        } catch (Exception e) {
            return BigDecimal.valueOf(-1);
        }
    }

    public BigDecimal retrieve(String toCode, String sourceCode) {
        return graphs.get(sourceCode + "|" + toCode);
    }

    //------------------------------------------获取汇率方法区-----------------------------------------------------

    //------------------------------------------公共方法区-----------------------------------------------------


    private JSONObject getForBaseMap(String url){
        JSONObject resultMap;
        try {
            ResponseEntity<String> response =
                    restTemplate.exchange(
                            url,
                            HttpMethod.GET,
                            new HttpEntity<String>(getAccessTokenHeader()),
                            String.class
                    );
            resultMap = JSONObject.parseObject(response.getBody());
            if (RegexUtil.checkObjectIsNull(resultMap)) {
                throw new ProgramException("系统异常");
            }
        } catch (Exception e) {
            resultMap = null;
        }
        return resultMap;
    }


    private HttpHeaders getAccessTokenHeader() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "APPCODE " + aliConfig.getAppCode());
        return headers;
    }

    //------------------------------------------公共方法区-----------------------------------------------------


}
